package com.atguigu.gulimall.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.constants.ProductConstants;
import com.atguigu.feign.clients.SearchFeignService;
import com.atguigu.feign.to.es.SkuEsModel;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.R;
import com.atguigu.feign.clients.DiscountService;
import com.atguigu.feign.clients.WareFeignService;
import com.atguigu.feign.to.SkuHasStockTo;
import com.atguigu.feign.to.SkuReductionTo;
import com.atguigu.feign.to.SpuBoundTo;
import com.atguigu.gulimall.product.entity.*;
import com.atguigu.gulimall.product.service.*;
import com.atguigu.gulimall.product.vo.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.atguigu.gulimall.product.dao.SpuInfoDao;
import com.atguigu.common.utils.Query;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

@Service("spuInfoService")
@Slf4j
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    private SpuInfoDescService spuInfoDescService;

    @Autowired
    private SpuImagesService spuImagesService;

    @Autowired
    private AttrService attrService;

    @Autowired
    private ProductAttrValueService productAttrValueService;

    @Autowired
    private SkuInfoService skuInfoService;

    @Autowired
    private SkuImagesService skuImagesService;

    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    private DiscountService discountService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private WareFeignService wareFeignService;

    @Autowired
    private SearchFeignService searchProductClient;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }


    //发布商品   TODO 高级部分 完善
    @Override
    @Transactional
    public void saveSpuSaveVo(SpuSaveVo vo) {
        //1.保存spu基本信息  pms_spu_info
        SpuInfoEntity spu = new SpuInfoEntity();
        BeanUtils.copyProperties(vo, spu);
        spu.setCreateTime(new Date());
        spu.setUpdateTime(new Date());
        log.info("保存spu基本信息：{}", spu);
        this.save(spu);

        //2.保存spu的描述图片  pms_spu_info_desc
        SpuInfoDescEntity spuInfoDesc = new SpuInfoDescEntity();
        spuInfoDesc.setSpuId(spu.getId());
        spuInfoDesc.setDecript(String.join(",", vo.getDecript()));
        log.info("保存spu的描述图片 ：{}", spuInfoDesc);
        spuInfoDescService.saveSpuInfoDesc(spuInfoDesc);

        //3.保存spu 图片集 pms_spu_images
        List<String> images = vo.getImages();
        spuImagesService.saveSpuImages(spu.getId(), images);

        //4. 保存spu 规格参数  pms_product_attr_value
        List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
        if (!CollectionUtils.isEmpty(baseAttrs)) {
            List<ProductAttrValueEntity> productAttrValueEntities = baseAttrs.stream().map(attr -> {
                ProductAttrValueEntity attrValueEntity = new ProductAttrValueEntity();
                AttrEntity byId = attrService.getById(attr.getAttrId());
                if (byId != null) {
                    attrValueEntity.setAttrName(byId.getAttrName());
                }
                attrValueEntity.setQuickShow(attr.getShowDesc());
                attrValueEntity.setSpuId(spu.getId());
                attrValueEntity.setAttrId(attr.getAttrId());
                attrValueEntity.setAttrValue(attr.getAttrValues());
                return attrValueEntity;
            }).collect(Collectors.toList());

            productAttrValueService.saveProductAttrValues(productAttrValueEntities);
        }

        //5. 保存spu 积分信息； gulimall_sms -> sms_spu_bounds
        Bounds bounds = vo.getBounds();
        SpuBoundTo spuBoundTo = new SpuBoundTo();
        BeanUtils.copyProperties(bounds, spuBoundTo);
        spuBoundTo.setSpuId(spu.getId());
        log.info("保存spu 积分信息，feign调用。");
        R r = discountService.saveSpuBounds(spuBoundTo);
        if (r.getCode() != 0) {
            log.error("保存spu 积分信息失败。");
        }

        //6. 保存spu对应的sku相关信息。
        List<Skus> skus = vo.getSkus();
        skus.forEach(sku -> {

            String defaultUrl = "";
            for (Images image : sku.getImages()) {
                if (image.getDefaultImg() == 1) {
                    defaultUrl = image.getImgUrl();
                }
            }
            /*private String skuName;
            private BigDecimal price;
            private String skuTitle;
            private String skuSubtitle;*/
            SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
            BeanUtils.copyProperties(sku, skuInfoEntity);
            skuInfoEntity.setBrandId(spu.getBrandId());
            skuInfoEntity.setCatalogId(spu.getCatalogId());
            skuInfoEntity.setSpuId(spu.getId());
            skuInfoEntity.setSaleCount(0L);
            skuInfoEntity.setSkuDefaultImg(defaultUrl);
            log.info("保存sku基本信息");
            //6.1) 保存sku基本信息 pms_sku_info
            skuInfoService.save(skuInfoEntity);

            List<Images> images1 = sku.getImages();
            List<SkuImagesEntity> imagesList = images1.stream().filter(img -> {
                return StringUtils.isNotBlank(img.getImgUrl());
            }).map(img -> {
                SkuImagesEntity skuImage = new SkuImagesEntity();
                skuImage.setDefaultImg(img.getDefaultImg());
                skuImage.setImgUrl(img.getImgUrl());
                skuImage.setSkuId(skuInfoEntity.getSkuId());
                return skuImage;
            }).collect(Collectors.toList());
            //6.2） 保存sku 图片信息 pms_sku_images
            log.info("保存sku 图片信息");
            skuImagesService.saveBatch(imagesList);

            //6.3) 保存sku 销售属性&值 pms_sku_sale_attr_value
            List<Attr> attr = sku.getAttr();
            List<SkuSaleAttrValueEntity> collect = attr.stream().map(item -> {
                SkuSaleAttrValueEntity attrValueEntity = new SkuSaleAttrValueEntity();
                BeanUtils.copyProperties(item, attrValueEntity);
                attrValueEntity.setSkuId(skuInfoEntity.getSkuId());
                return attrValueEntity;
            }).collect(Collectors.toList());
            log.info("保存sku 销售属性&值");
            skuSaleAttrValueService.saveBatch(collect);

            //6.4） 保存sku 优惠/满减等信息 gulimall_sms -> sms_sku_ladder/sms_sku_full_reduction
            SkuReductionTo skuReductionTo = new SkuReductionTo();
            BeanUtils.copyProperties(sku, skuReductionTo);
            skuReductionTo.setSkuId(skuInfoEntity.getSkuId());
            R r1 = discountService.saveSkuReductionTo(skuReductionTo);
            if (r1.getCode() != 0) {
                log.error("保存sku 优惠/满减等信息 错误");
            }

        });


    }

    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        /*{
           sidx: 'id',//排序字段
           order: 'asc/desc',//排序方式
           key: '华为',//检索关键字
           catelogId: 6,//三级分类id
           brandId: 1,//品牌id
           status: 0,//商品状态
        }*/
        LambdaQueryWrapper<SpuInfoEntity> queryWrapper = new LambdaQueryWrapper<SpuInfoEntity>();
        String catelogId = (String) params.get("catelogId");
        if(StringUtils.isNotBlank(catelogId) && !"0".equals(catelogId)){
            queryWrapper.eq(SpuInfoEntity::getCatalogId,catelogId);
        }

        String brandId = (String) params.get("brandId");
        if(StringUtils.isNotBlank(brandId) && !"0".equals(brandId)){
            queryWrapper.eq(SpuInfoEntity::getBrandId,brandId);
        }

        String status = (String) params.get("status");
        if(StringUtils.isNotBlank(status)){
            queryWrapper.eq(SpuInfoEntity::getPublishStatus,status);
        }

        String key = (String) params.get("key");
        if(StringUtils.isNotBlank(key)){
            queryWrapper.and(w->{
                w.eq(SpuInfoEntity::getId,key).or().like(SpuInfoEntity::getSpuName,key);
            });
        }
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);
    }

    //商品上架
    @Override
    public void spuUp(Long spuId) {
        //根据spuId获取全部Sku
        List<SkuInfoEntity> skuInfoEntities = skuInfoService.getSkusBySpuId(spuId);

        if(!skuInfoEntities.isEmpty()){
            //TODO 1. 发送远程请求，查看是否还有库存。
            Map<Long, Boolean> stockMap = null;
            try {
                List<Long> collect1 = skuInfoEntities.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
                R hasstock = wareFeignService.hasstock(collect1);
                stockMap = hasstock.getData(new TypeReference<List<SkuHasStockTo>>(){})
                        .stream().collect(Collectors.toMap(SkuHasStockTo::getSkuId, SkuHasStockTo::getHasStock));
            } catch (Exception e) {
                log.error("远程查看库存失败，错误为：{}",e);
            }


            SkuInfoEntity skuInfoEntity = skuInfoEntities.get(0);
            //TODO 3. 查询品牌和分类的信息
            BrandEntity brandEntity = brandService.getById(skuInfoEntity.getBrandId());
            CategoryEntity categoryEntity = categoryService.getById(skuInfoEntity.getCatalogId());

            //TODO 4. 查出当前sku的所有可以被用来检索的规格属性
            //获取spu全部属性值
            List<ProductAttrValueEntity> baseAttr = productAttrValueService.baseAttrListForSpu(spuId);
            List<Long> attrIds = baseAttr.stream().map(attr -> {
                return attr.getAttrId();
            }).collect(Collectors.toList());
            //在spu全部属性中找到检索属性
            List<Long> searchAttrIds = attrService.selectSearchAttrIds(attrIds);
            Set<Long> setId = new HashSet<>(searchAttrIds);

            List<SkuEsModel.attr> skuEsModelAttrs = baseAttr.stream().filter(attr -> {
                return setId.contains(attr.getAttrId());
            }).map(attr -> {
                SkuEsModel.attr attr1 = new SkuEsModel.attr();
                BeanUtils.copyProperties(attr, attr1);
                return attr1;
            }).collect(Collectors.toList());


            Map<Long, Boolean> finalStockMap = stockMap;
            //****将全部skuEntity 转换为 skuEsModel
            List<SkuEsModel> skuEsModels = skuInfoEntities.stream().map(sku -> {
                SkuEsModel skuEsModel = new SkuEsModel();
                BeanUtils.copyProperties(sku,skuEsModel);
                //填充字段不一致的值
                skuEsModel.setSkuPrice(sku.getPrice());
                skuEsModel.setSkuImg(sku.getSkuDefaultImg());
                //设置品牌和分类的信息
                skuEsModel.setCatalogName(categoryEntity.getName());
                skuEsModel.setBrandName(brandEntity.getName());
                skuEsModel.setBrandImg(brandEntity.getLogo());
                skuEsModel.setAttrs(skuEsModelAttrs);
                if(finalStockMap == null){
                    skuEsModel.setHasStock(true);
                }else{
                    skuEsModel.setHasStock(finalStockMap.get(sku.getSkuId()));
                }
                //TODO 2. 热度评分 0
                skuEsModel.setHotScore(0L);
                return skuEsModel;
            }).collect(Collectors.toList());

            R r = searchProductClient.productSaveEs(skuEsModels);
            if(r.getCode() == 0){
                //远程调用，上架成功 修改当前spu状态
                baseMapper.updateSpuStatus(spuId, ProductConstants.SpuStatusEnum.SPU_UP.getCode());
            }else{
                //远程调用失败， TODO 重复调用？ 接口幂等性； 重试机制
            }

        }
    }

}